﻿using JigLibX.Collision;
using JigLibX.Geometry;
using JigLibX.Math;
using JigLibX.Physics;
using Microsoft.Xna.Framework;
using SolarWinds.Helpers;
using SolarWinds.Screens;

namespace SolarWinds.Shapes
{
    class AsteroidShape : ModelShape
    {
        private readonly Body mBody;
        private readonly CollisionSkin mSkin;

        public bool Killed = false;
        public Vector3 Direction { get; set; }
        public Vector3 Spin { get; set; }
        private Vector3 mCenterOfMass;

        public AsteroidShape(Game game)
            : base(game, "asteroid0" + (int)RandomHelper.RandomBetween(1, 5))
        {
            BoundingBoxVisible = true;
            BoundingSphereVisible = true;

            mBody = new Body();
            mBody.ExternalData = this;

            mSkin = new CollisionSkin(mBody);
            mBody.CollisionSkin = mSkin;
        }

        protected override void Dispose(bool disposing)
        {
            base.Dispose(disposing);

            if (disposing)
            {
                mBody.DisableBody();
            }
        }

        protected override void LoadContent()
        {
            base.LoadContent();
            
            var sphere = new Sphere(BoundingSphere.Center, BoundingSphere.Radius * Scale.X);
            mSkin.AddPrimitive(sphere, new MaterialProperties(0.8f, 0.8f, 0.7f));
            
            mCenterOfMass = PhysicsHelper.SetMass(70.0f, mSkin, mBody);
            
            mBody.MoveTo(Position, Matrix.Identity);
            mBody.AngularVelocity = RandomHelper.RandomVector3();
            mBody.Velocity = Direction;
            mSkin.ApplyLocalTransform(new Transform(-mCenterOfMass, Matrix.Identity));
            mBody.EnableBody();

            PhysicsSystem.CurrentPhysicsSystem.CollisionSystem.AddCollisionSkin(mSkin);

            mSkin.callbackFn += new CollisionCallbackFn(SkinCallbackFn);
        }

        bool SkinCallbackFn(CollisionSkin owner, CollisionSkin collidee)
        {
            if (collidee.Owner.ExternalData is AsteroidShape)
            {
                // collision with other asteroid
                return true;
            }
            if (collidee.Owner.ExternalData is ShipShape ||
                collidee.Owner.ExternalData is ProjectileShape)
            {
                // collison with ship or projectile
                Killed = true;
                return false;
            }

            return true;
        }

        // TODO move to a base class - see ship class
        public override void Update(GameTime gameTime)
        {
            base.Update(gameTime);

            Position = mBody.Position;
            Rotation = Quaternion.CreateFromRotationMatrix(
                mSkin.GetPrimitiveLocal(0).Transform.Orientation *
                mBody.Orientation);
        }
    }
}
